import { defineStore } from "pinia";
import {
  store,
  router,
  resetRouter,
  routerArrays,
  storageLocal,
  isString,
  isIncludeAllChildren
} from "../utils";
import {
  type LoginData,
  getCurrentUser,
  refreshAccessTokenApi,
  revokeRefreshTokenApi,
  userLoginApi
} from "@/api/user";
import { useMultiTagsStoreHook } from "./multiTags";
import { eventEngine } from "@/services/eventEngine";
import { useNotificationStore } from "./notificationStore";
import { useAccountAggregationStore } from "./accountAggregationStore";
import { getDeviceInfo } from "@/utils/device";
export const userKey = "user-info";

export interface UserInfo {
  /** accessToken */
  accessToken?: string;
  /** 头像 */
  avatar?: string;
  /** 用户名 */
  username?: string;
  /** 昵称 */
  nickname?: string;
  /** 当前登录用户的角色 */
  roles?: Array<string>;
  /** 当前登录用户的按钮级别权限 */
  permissions?: Array<string>;
}

/** 格式化token（jwt格式） */
export const formatToken = (token: string): string => {
  return "Bearer " + token;
};

/** 是否有按钮级别的权限（根据登录接口返回的`permissions`字段进行判断）*/
export const hasPerms = (value: string | Array<string>): boolean => {
  if (!value) return false;
  const allPerms = "*:*:*";
  const { permissions } = useUserStoreHook();
  if (!permissions) return false;
  if (permissions.length === 1 && permissions[0] === allPerms) return true;
  const isAuths = isString(value)
    ? permissions.includes(value)
    : isIncludeAllChildren(value, permissions);
  return isAuths ? true : false;
};

export const useUserStore = defineStore("pure-user", {
  state: () => ({
    // accessToken
    accessToken: "",
    // 过期时间
    expire_at: 0,
    // 头像
    avatar: storageLocal().getItem<UserInfo>(userKey)?.avatar ?? "",
    // 用户名
    username: storageLocal().getItem<UserInfo>(userKey)?.username ?? "",
    // 昵称
    nickname: storageLocal().getItem<UserInfo>(userKey)?.nickname ?? "",
    // 页面级别权限
    roles: storageLocal().getItem<UserInfo>(userKey)?.roles ?? [],
    // 按钮级别权限
    permissions: storageLocal().getItem<UserInfo>(userKey)?.permissions ?? []
  }),
  actions: {
    /** 存储用户信息 */
    updateUserStore(userInfo: UserInfo) {
      this.avatar = userInfo.avatar;
      this.username = userInfo.username;
      this.nickname = userInfo.nickname;
      this.roles = userInfo.roles;
      this.permissions = userInfo.permissions;
      storageLocal().setItem(userKey, {
        avatar: userInfo.avatar,
        username: userInfo.username,
        nickname: userInfo.nickname,
        roles: userInfo.roles,
        permissions: userInfo.permissions
      });
    },
    /** 存储accessToken */
    setAccessToken(accessToken: string, expire_at: number) {
      this.accessToken = accessToken;
      this.expire_at = expire_at;
    },
    /** 获取accessToken */
    getFormattedToken() {
      return this.accessToken ? formatToken(this.accessToken) : "";
    },
    /** 获取accessToken是否过期 */
    isAccessTokenExpired() {
      // 提前10秒过期
      return !this.expire_at || this.expire_at - 10000 < Date.now();
    },
    /** 清空accessToken */
    clearAccessTokenAndUserStore() {
      this.accessToken = "";
      this.expire_at = 0;
      storageLocal().removeItem(userKey);
    },
    /**
     * Logs in a user using their username and password.
     * @param data - The login data containing username and password.
     * @returns A promise that resolves to the authenticated user's information.
     */
    async loginByUsername(data: LoginData): Promise<null> {
      const deviceInfo = getDeviceInfo();
      const {
        data: { access_token, expire_at }
      } = await userLoginApi({ ...data, device_info: deviceInfo });
      if (!access_token) {
        throw new Error("未获取到 accessToken");
      }

      // Store the retrieved access token
      this.setAccessToken(access_token, expire_at);

      // Fetch the current user's information using the access token
      const { success, data: currentUserData } = await getCurrentUser();

      if (!success) {
        throw new Error("获取用户信息失败");
      }

      // Construct the UserInfo object with the retrieved data
      const userInfo: UserInfo = {
        accessToken: access_token,
        avatar: currentUserData.avatar,
        username: currentUserData.name,
        nickname: currentUserData.name_cn,
        roles: currentUserData.roles?.split(",") || [],
        permissions: currentUserData.permissions?.split(",") || []
      };

      // Store the user data locally
      this.updateUserStore(userInfo);

      return null;
    },
    /** 刷新 token
     * success: refresh and save access token
     * failure: log out
     */
    async refreshAccessToken() {
      const resp = await refreshAccessTokenApi();
      const { access_token, expire_at } = resp.data;
      this.setAccessToken(access_token, expire_at);
    },
    /** 前端登出（不调用接口） */
    logOut() {
      useAccountAggregationStore().dispose();
      useNotificationStore().dispose();
      eventEngine.dispose();
      revokeRefreshTokenApi().catch();
      this.username = "";
      this.roles = [];
      this.permissions = [];
      this.clearAccessTokenAndUserStore();
      useMultiTagsStoreHook().handleTags("equal", [...routerArrays]);
      resetRouter();
      router.push("/login");
    }
  }
});

export function useUserStoreHook() {
  return useUserStore(store);
}
